---
title: Cameras
slug: /cameras
section: Fundamentals
---

Cameras are attached to scenes and can be changed by
setting [[Scene.camera]]. By default, a [[Scene]] is initialized with a
[[Camera]] that doesn't move and is centered on the screen.

### Focus

Cameras have a position ([[Camera.x|x]], [[Camera.y|y]]) which means they center around a specific
[point](/docs/math#vectors).

If a camera is following an [Actor](/docs/actors), it will ensure the actor is always at the
center of the screen. You can use [[Camera.x]] and [[Camera.y]] instead if you wish to
offset the focal point.

### Camera zooming

To adjust the zoom for your game, use [[Camera.zoom]] which will scale the
game accordingly. You can pass a duration to transition between zoom levels.

This can be useful as a way to scale up your game.

### Camera strategies

Cameras can implement a number of strategies to track, follow, or exhibit custom behavior in relation to a target. A common reason to use a
strategy is to have the [[Camera]] follow an [[Actor]].

In order to use the different built-in strategies, you can access [[Camera.strategy]].

:::warning

It is important to add the camera strategy in your Engine, Scene, or Actor's `onInitialize()`, the strategy will automatically update itself so do not put it in a update/draw lifecycle event.

:::

Lock the camera exactly to the center of the actor's bounding box

```typescript
game.currentScene.camera.strategy.lockToActor(actor);
```

Lock the camera to one axis of the actor, in this case follow the actors x position

```typescript
game.currentScene.camera.strategy.lockToActorAxis(actor, ex.Axis.X);
```

Elastically move the camera to an actor in a smooth motion see [[ElasticToActorStrategy]] for details

```typescript
game.currentScene.camera.strategy.elasticToActor(actor, cameraElasticity, cameraFriction);
```

Keep the actor within a circle around the focus

```typescript
game.currentScene.camera.strategy.radiusAroundActor(actor, radius);
```

Keep the camera limited within the given constraints.  
Make sure that the camera bounds are at least as large as the viewport size.

```typescript
let boundingBox = new BoundingBox(leftBorder, topBorder, rightBorder, bottomBorder);
game.currentScene.camera.strategy.limitCameraBounds(boundingBox);
```

#### Multiple strategies

Multiple strategies can be applied to the camera. Strategies are applied in the order they were added. 

For example: Let's say a `lockToActor` strategy and a `limitCameraBounds` strategy is added, in that order. When the
strategies are processed, the camera will first lock to the actor, then, as the camera approaches the configured bounds
of `limitCameraBounds` it is limited to those contraints. 

In this example, the `limitCameraBounds` applies its effect on _top_ of the earlier `lockToActor` strategy. 


#### Custom strategies

Custom strategies can be implemented by extending the [[CameraStrategy]] interface and added to cameras to build novel behavior with `ex.Camera.addStrategy<T>(new MyCameraStrategy<T>())`.

As shown below a camera strategy calculates a new camera position vector every frame given a target type, camera, engine, and elapsed delta in milliseconds.

```typescript
/**
 * Interface that describes a custom camera strategy for tracking targets
 */
export interface CameraStrategy<T> {
  /**
   * Target of the camera strategy that will be passed to the action
   */
  target: T;

  /**
   * Camera strategies perform an action to calculate a new focus returned out of the strategy
   */
  action: (target: T, camera: Camera, engine: Engine, elapsed: number) => Vector;
}
```

When implementing custom strategies consider referencing the camera's current position with `camera.getFocus()` and
calculate the next position from that vector. This allows strategies to be composed gracefully. 

LockCameraToActorAxisStrategy sample:

```typescript
export class LockCameraToActorAxisStrategy implements CameraStrategy<Actor> {
  constructor(
    public target: Actor,
    public axis: Axis
  ) {}
  public action = (target: Actor, cam: Camera, _eng: Engine, elapsed: number) => {
    const center = target.center;
    const currentFocus = cam.getFocus();
    if (this.axis === Axis.X) {
      return new Vector(center.x, currentFocus.y);
    } else {
      return new Vector(currentFocus.x, center.y);
    }
  };
}
```

When configuring your custom strategy the first argument, `target`, can be of any type. While [[Actor]] is commonly the
target, it can anything, such as a `BoundingBox`.

#### Adding and removing strategies

In the above examples we used convenience helpers, such as `game.currentScene.camera.strategy.lockToActor(actor)`, to
add strategies to our scene. Occassionally you may need a bit more control over the strategy array. This can be done
via the following methods and properties:

 - `addStrategy<T extends CameraStrategy<any>[]>(...cameraStrategies: T)`
    - Adds the given strategy to the end of the strategy array. The built in convenience helpers are wrappers for `addStrategy()`.
    - Multiple strategies can be passed as arguments and they will be appended to the end of the strategy array. 
 - `removeStrategy<T>(cameraStrategy: CameraStrategy<T>)`
    - Removes the given strategy from the strategy array.
 - `clearAllStrategies()`
    - Clears all camera strategies from the camera.
 - `setStrategies<T extends CameraStrategy<any>[]>(cameraStrategies: T)`
    - Overwrites the current array of strategies with the provided set.
 - `strategies`
    - The camera's strategy array 


### Camera shake

To add some fun effects to your game, the [[Camera.shake]] method
will do a random shake. This is great for explosions, damage, and other
in-game effects.

### Camera lerp

"Lerp" is short for [Linear Interpolation](http://en.wikipedia.org/wiki/Linear_interpolation)
and it enables the camera focus to move smoothly between two points using timing functions.
Use [[Camera.move]] to ease to a specific point using a provided [[Util.EasingFunction|EasingFunction]].

```typescript
export interface EasingFunction {
  (currentTime: number, startValue: number, endValue: number, duration: number): number;
}

// or any builtin

const linear = ex.EasingFunctions.Linear;
const easinQuad = ex.EasingFunctions.EaseInQuad;
// ... and more!

```


